#include <iostream>
#include <memory>
#include <functional>
using namespace std;

#include <string>
#include <cstddef>
#include <concepts>

#include <iostream>
#include <map>
#include <memory>

#define FUNC function<void*(void)>

using namespace std;

class Reflector
{
private:
    map<std::string, FUNC>objectMap;
    static shared_ptr<Reflector> ptr;

public:
    void* CreateObject(const string& str)
    {
        for (auto& x : objectMap)
        {
            if (x.first == str)
                return x.second();
        }
        return nullptr;
    }

    void Register(const string& class_name, FUNC&& generator)
    {
        objectMap[class_name] = generator;
    }



    static shared_ptr<Reflector> Instance()
    {
        if (ptr == nullptr)
        {
            ptr.reset(new Reflector());
        }

        return ptr;
    }

};

shared_ptr<Reflector> Reflector::ptr = nullptr;

class RegisterAction
{
public:
    RegisterAction(const string& class_name, FUNC&& generator)
    {
        Reflector::Instance()->Register(class_name, forward<FUNC>(generator));
    }
};

#define REGISTER(CLASS_NAME) \
RegisterAction g_register_action_##CLASS_NAME(#CLASS_NAME, []()\
{\
    return new CLASS_NAME(); \
});


class Base
{
public:
    explicit Base() = default;
    virtual void Print()
    {
        cout << "Base" << endl;
    }
};
REGISTER(Base);

class DeriveA : public Base
{
public:
    void Print() override
    {
        cout << "DeriveA" << endl;
    }
};
REGISTER(DeriveA);


// Alternative ways to apply the same constraint:
// template<typename T>
//    requires Hashable<T>
// void f(T) {}
//
// template<typename T>
// void f(T) requires Hashable<T> {}


#include <coroutine>
#include <iostream>
#include <stdexcept>
#include <thread>




class Sandwich {
    int* bread;
public:
    const int* freeze() const {

        return c;

    }
    int* c;
};


#include <iostream>
#include <string>


using namespace std;


#include <fstream>

class Channel
{
public:
    Channel(ostream* o = &std::cout) : trace_file(o) {}
    ~Channel()
    {
    }
    void Reset(ostream* o = &std::cout)
    {
        trace_file = o;
    }
    ostream& getInstance()
    {
        return *trace_file;
    }
private:
    ostream* trace_file;
};



#pragma once

#include <string>
#include <chrono>
#include <algorithm>
#include <fstream>

#include <thread>

struct ProfileResult
{
    std::string Name;
    long long Start, End;
    uint32_t ThreadID;
};

struct InstrumentationSession
{
    std::string Name;
};

class Instrumentor
{
private:
    InstrumentationSession* m_CurrentSession;
    std::ofstream m_OutputStream;
    int m_ProfileCount;
// this shoud private
    Instrumentor()
        : m_CurrentSession(nullptr), m_ProfileCount(0)
    {
    }
public:
    void BeginSession(const std::string& name, const std::string& filepath = "results.json")
    {
        m_OutputStream.open(filepath);
        WriteHeader();
        m_CurrentSession = new InstrumentationSession{ name };
    }

    void EndSession()
    {
        WriteFooter();
        m_OutputStream.close();
        delete m_CurrentSession;
        m_CurrentSession = nullptr;
        m_ProfileCount = 0;
    }

    void WriteProfile(const ProfileResult& result)
    {
        if (m_ProfileCount++ > 0)
            m_OutputStream << ",";

        std::string name = result.Name;
        std::replace(name.begin(), name.end(), '"', '\'');

        m_OutputStream << "{";
        m_OutputStream << "\"cat\":\"function\",";
        m_OutputStream << "\"dur\":" << (result.End - result.Start) << ',';
        m_OutputStream << "\"name\":\"" << name << "\",";
        m_OutputStream << "\"ph\":\"X\",";
        m_OutputStream << "\"pid\":0,";
        m_OutputStream << "\"tid\":" << result.ThreadID << ",";
        m_OutputStream << "\"ts\":" << result.Start;
        m_OutputStream << "}";

        m_OutputStream.flush();
    }

    void WriteHeader()
    {
        m_OutputStream << "{\"otherData\": {},\"traceEvents\":[";
        m_OutputStream.flush();
    }

    void WriteFooter()
    {
        m_OutputStream << "]}";
        m_OutputStream.flush();
    }

    static Instrumentor& Get()
    {
        static Instrumentor instance;
        return instance;
    }
};

class InstrumentationTimer
{
public:
    InstrumentationTimer(const char* name)
        : m_Name(name), m_Stopped(false)
    {
        m_StartTimepoint = std::chrono::high_resolution_clock::now();
    }

    ~InstrumentationTimer()
    {
        if (!m_Stopped)
            Stop();
    }

    void Stop()
    {
        auto endTimepoint = std::chrono::high_resolution_clock::now();

        long long start = std::chrono::time_point_cast<std::chrono::microseconds>(m_StartTimepoint).time_since_epoch().count();
        long long end = std::chrono::time_point_cast<std::chrono::microseconds>(endTimepoint).time_since_epoch().count();

        uint32_t threadID = std::hash<std::thread::id>{}(std::this_thread::get_id());
        Instrumentor::Get().WriteProfile({ m_Name, start, end, threadID });

        m_Stopped = true;
    }
private:
    const char* m_Name;
    std::chrono::time_point<std::chrono::high_resolution_clock> m_StartTimepoint;
    bool m_Stopped;
};


void fun1() {

    InstrumentationTimer timer("fun1");

    int i = 0;
    do {
        i++;
    } while (i < 1000000);


}



void fun2() {
    InstrumentationTimer timers("fun2");


    int i = 0;
    do {
        i++;
    } while (i < 1000000);


}



#include <vector>

using namespace std;

void update(int node, vector<int >& vec) {

    int l = 2 * node + 1;  //数组下标从0开始，这里注意l = 2* node + 1
    int r = l + 1;

    while (l < vec.size())
    {


        if (r < vec.size() && vec[l] < vec[r]) l = r;  //注意这里 一方面要保证右节点存在才处理，另一方面总是node和l比较，因为node和子节点比较的时候，有可能子节点没有r节点

        if (vec[node] < vec[l]) {

            swap(vec[node], vec[l]);

            node = l;
            l = 2 * node + 1;
            r = l + 1;
        }
        else return;
    }

}

void rebuild(vector<int>& vec) {

    int node = vec.size() / 2 - 1;   //向下取整  ，如有三个节点时 3/2 -1 = 1 -1 = 0 
    for (int i = node; i >= 0; i--) {
        update(i, vec);
    }

}

int main()
{


    Instrumentor::Get().BeginSession("Profilesssss");
    fun1();
    fun2();
    Instrumentor::Get().EndSession();
    return 0;

}






